package top.tagao.multithread_04_sync;

/**
 * @author fu-xiao-liu
 * @Date 2022/3/29 21:39
 * 例子：创建三个窗口卖票，总票数为100张.使用继承Thread类的方式
 *
 * 1.问题：卖票过程中，出现了重票、错票 -->出现了线程的安全问题
 * 2.问题出现的原因：当某个线程操作车票的过程中，尚未操作完成时，其他线程参与进来，也操作车票。
 * 3.如何解决：当一个线程a在操作ticket的时候，其他线程不能参与进来。直到线程a操作完ticket时，其他
 *            线程才可以开始操作ticket。这种情况即使线程a出现了阻塞，也不能被改变。
 * 4.在Java中，我们通过同步机制，来解决线程的安全问题。
 *
 *  方式一：同步代码块
 *
 *   synchronized(同步监视器){
 *      //需要被同步的代码
 *
 *   }
 *  说明：1.操作共享数据的代码，即为需要被同步的代码。  --> 不能包含代码多了，也不能包含代码少了。
 *       2.共享数据：多个线程共同操作的变量。比如：ticket就是共享数据。
 *       3.同步监视器，俗称：锁。任何一个类的对象，都可以充当锁。
 *          要求：多个线程必须要共用同一把锁。
 *   说明：在继承Thread类创建多线程的方式中，慎用this充当同步监视器，考虑使用当前类充当同步监视器。
 *
 */
public class Sync_01_block {
    public static void main(String[] args) {
        WinThread01 winThread01 = new WinThread01();
        WinThread01 winThread02 = new WinThread01();
        WinThread01 winThread03 = new WinThread01();
        winThread01.start();
        winThread02.start();
        winThread03.start();
    }

}

class WinThread01 extends Thread {
    static  int ticket = 100;

    @Override
    public void run() {
        while (true) {
            synchronized (WinThread01.class)  {
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + ":卖票，票号为：" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

